home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / BLOWUP.ZIP / BLOWUP.C next >
C/C++ Source or Header  |  1991-11-24  |  15KB  |  579 lines

  1. #include <conio.h>
  2. #include <graphics.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <time.h>
  6. #include <ctype.h>
  7. #include "mouse.c"
  8.  
  9. #define YES 1
  10. #define NO  0
  11.  
  12. #define XPX 15        /* X pixels by square */
  13. #define YPX 15        /* Y pixels by square */
  14.  
  15. #define DEFCX 30    /* Default number of squares */
  16. #define DEFCY 28
  17.  
  18. #define MINE 255-'0'    /* So that when it prints, it prints char 0xff */
  19.  
  20. #define STSQUARE struct stsquare
  21.  
  22. STSQUARE {
  23.    unsigned char value;        /* Number of mines in the surround squares */
  24.    unsigned char sqopen;    /* Square is open */
  25.    unsigned char sqpress;    /* Square is pressed */
  26.    unsigned char sqmark;    /* Square is marked */
  27. } *psquare;
  28.  
  29. #define value(x,y)   (psquare+(x)*ncy+(y))->value
  30. #define sqopen(x,y)  (psquare+(x)*ncy+(y))->sqopen
  31. #define sqpress(x,y) (psquare+(x)*ncy+(y))->sqpress
  32. #define sqmark(x,y)  (psquare+(x)*ncy+(y))->sqmark
  33.  
  34. int XST,    /* Offset of first pixel X */
  35.     YST,
  36.     ncx,    /* Number of squares in X */
  37.     ncy,
  38.     cmines,    /* Mines discovered */
  39.     initmines,    /* Number of initial mines */
  40.     sqclosed,    /* Squares still closed */
  41.     maxy;    /* Max. number of y pixels of the screen */
  42.  
  43. void Graph_init(void);
  44. void Read_param(int argc, char *argv[]);
  45. void Set_mines(int nminas);
  46. void Set_square(int x, int y, int status);
  47. void Mouse_set(void);
  48. void Draw_squares(void);
  49. int  Do_all(void);
  50. void Blow_up(void);
  51. void Open_square(int x, int y);
  52. int  Open_near_squares(int x, int y);
  53.  
  54. /************************************************************************/
  55.  
  56. void main(int argc, char *argv[])
  57. {
  58.    if (!mouse_reset()) {
  59.       cputs(" ERROR: I can't find a mouse driver\r\n");
  60.       exit(2);
  61.    }
  62.    Graph_init();
  63.    Read_param(argc, argv);
  64.    Mouse_set();
  65.    do {
  66.       randomize();
  67.       cleardevice();
  68.       Set_mines(cmines=initmines);
  69.       mouse_enable();
  70.       Draw_squares();
  71.    }
  72.    while (Do_all() != '\x1b');
  73.    closegraph();
  74. }
  75.  
  76. /*************************************************************************
  77. *                                                                        *
  78. *                           F U N C T I O N S                            *
  79. *                                                                        *
  80. *************************************************************************/
  81.  
  82. /*----------------------------------------------------------------------*/
  83.  
  84. void Graph_init(void)
  85. {
  86.    int graphdriver=DETECT, graphmode, errorcode;
  87.  
  88.    errorcode=registerbgidriver(EGAVGA_driver);
  89.    if(errorcode < 0) {
  90.      cprintf("\n\rGraphics System Error: %s\n",grapherrormsg(errorcode));
  91.      exit(98);
  92.    }
  93.    initgraph(&graphdriver, &graphmode, "");
  94.    errorcode=graphresult();
  95.    if(errorcode!=grOk) {
  96.      printf(" Graphics System Error: %s\n",grapherrormsg(errorcode));
  97.      exit(98);
  98.    }
  99.    maxy=getmaxy();
  100. }    /* Graph_init */
  101.  
  102. /*----------------------------------------------------------------------*/
  103.  
  104. void Read_param(int argc, char *argv[])
  105. {
  106.    int x, y, m;
  107.  
  108.    x=y=m=0;
  109.    if (argc!=1) {
  110.       if (!isdigit(*argv[1])) {
  111.      closegraph();
  112.      cprintf("Usage is: %s [x] [y] [m]\r\n\n"
  113.          "Where x is the horizontal size\r\n"
  114.          "      y is the vertical size\r\n"
  115.          "      m is the number of mines\r\n\n"
  116.          " Left mouse button: Open the square\r\n"
  117.          "Right mouse button: Mark the square\r\n"
  118.          "                    -The first time puts a 'mine' mark\r\n"
  119.          "                    -The second time puts a 'possible "
  120.                                      "mine' mark\r\n"
  121.          "                    -The third time unmarks the square\r\n"
  122.          "Left+Right buttons: Open the surrounded squares only if "
  123.                              "the count of mines\r\n"
  124.                  "                     is equal to the number in the square",argv[0]);
  125.      exit (1);
  126.       }
  127.       switch (argc) {
  128.      case 4: m=atoi(argv[3]);
  129.      case 3: y=atoi(argv[2]);
  130.      case 2: x=atoi(argv[1]);
  131.       }
  132.    }
  133.    XST=100;
  134.    ncx=DEFCX;
  135.    if (maxy==479) {
  136.       YST=30;
  137.       ncy=DEFCY;
  138.    }
  139.    else {
  140.       YST=25;
  141.       ncy=20;
  142.    }
  143.    if (x>0 && x<ncx)
  144.       ncx=x;
  145.    if (y>0 && y<ncy) {
  146.       YST+=((ncy-y)*YPX)>>1;
  147.       ncy=y;
  148.    }
  149.    initmines= m ? m : ncx*ncy*4/25;    /* There are about 16% of mines */
  150.    if ((psquare=calloc(ncx*ncy, sizeof(STSQUARE)))==NULL) {
  151.       closegraph();
  152.       cputs("ERROR: Not enought memory");
  153.       exit(3);
  154.    }
  155. }    /* Read_param */
  156.  
  157. /*----------------------------------------------------------------------*/
  158.  
  159. void Set_mines(int nminas)
  160. {
  161.    STSQUARE *p;
  162.    int i, x, y, a, b;
  163.  
  164.    sqclosed=ncx*ncy-nminas;
  165.    p=psquare;
  166.    for (i=ncx*ncy; i>0; i--, p++)
  167.       p->value = p->sqopen = p->sqpress = p->sqmark = NO;
  168.    for (i=nminas; i>0; i--) {
  169.       while (value(x=random(ncx), y=random(ncy)) == MINE)
  170.      ;
  171.       value(x,y)=MINE;
  172.    }
  173.    for (x=ncx-1; x>=0; x--) {
  174.       for (y=ncy-1; y>=0; y--) {
  175.      if (value(x,y) == MINE)
  176.         continue;
  177.      a=x-1;
  178.      b=y-1;
  179.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  180.         value(x,y)+=(value(a,b) == MINE);
  181.      a++;
  182.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  183.         value(x,y)+=(value(a,b) == MINE);
  184.      a++;
  185.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  186.         value(x,y)+=(value(a,b) == MINE);
  187.      b++;
  188.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  189.         value(x,y)+=(value(a,b) == MINE);
  190.      a-=2;
  191.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  192.         value(x,y)+=(value(a,b) == MINE);
  193.      b++;
  194.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  195.         value(x,y)+=(value(a,b) == MINE);
  196.      a++;
  197.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  198.         value(x,y)+=(value(a,b) == MINE);
  199.      a++;
  200.      if (a>=0 && b>=0 && a<ncx && b<ncy)
  201.         value(x,y)+=(value(a,b) == MINE);
  202.       }
  203.    }
  204. }    /* Set_mines */
  205.  
  206. /*----------------------------------------------------------------------*/
  207.  
  208. /*
  209.    If status=1 then draw the square up, if it's 0 then draw it down
  210. */
  211. void Set_square(int x, int y, int status)
  212. {
  213.    int xl, xr, yt, yb;
  214.  
  215.    mouse_disable();
  216.    xl=XST+XPX*x;
  217.    xr=xl+XPX-1;
  218.    yt=YST+YPX*y;
  219.    yb=yt+YPX-1;
  220.    setfillstyle(SOLID_FILL, LIGHTGRAY);
  221.    bar(xl, yt, xr, yb);
  222.    if (status) {
  223.       setcolor(WHITE);
  224.       line(xl,yt,xl,yb-1);
  225.       line(xl,yt,xr-1,yt);
  226.       setcolor(DARKGRAY);
  227.       line(xr,yb,xl,yb);
  228.       line(xr,yb,xr,yt);
  229.       switch (sqmark(x,y)) {
  230.      case 2 : setfillstyle(SOLID_FILL, LIGHTBLUE);
  231.           setcolor(LIGHTBLUE);
  232.           break;
  233.      case 1 : setfillstyle(SOLID_FILL, LIGHTRED);
  234.           setcolor(LIGHTRED);
  235.           break;
  236.      default: setcolor(LIGHTGRAY);
  237.       }
  238.       fillellipse(XST+XPX*x+XPX/2, YST+YPX*y+YPX/2, 3, 3);
  239.       switch (sqmark(x,y)) {
  240.      case 2 :
  241.      case 1 : setfillstyle(SOLID_FILL, YELLOW);
  242.           setcolor(YELLOW);
  243.           fillellipse(XST+XPX*x+XPX/2, YST+YPX*y+YPX/2, 1, 1);
  244.       }
  245.    }
  246.    else {
  247.       sqclosed--;
  248.       setcolor(DARKGRAY);
  249.       line(xl,yt,xl,yb);
  250.       line(xl,yt,xr,yt);
  251.    }
  252.    mouse_enable();
  253. }    /* Set_square */
  254.  
  255. /*----------------------------------------------------------------------*/
  256.  
  257. void Mouse_set(void)
  258. {
  259.    mouse_horizontal_range(XST, XST+XPX*ncx-3);
  260.    mouse_vertical_range(YST, YST+YPX*ncy-3);
  261. }    /* Mouse_set */
  262.  
  263. /*----------------------------------------------------------------------*/
  264.  
  265. void Draw_squares(void)
  266. {
  267.    int x, y;
  268.  
  269.    mouse_disable();
  270.    for (x=0; x<ncx; x++)
  271.       for (y=0; y<ncy; y++)
  272.      Set_square(x,y,1);
  273.    mouse_enable();
  274. }    /* Draw_squares */
  275.  
  276. /*----------------------------------------------------------------------*/
  277.  
  278. /*
  279.    Here we do all the job
  280. */
  281. int Do_all(void)
  282. {
  283.    int x, y, xant=-1, yant, mlstant, mrstant, cminasant=0, ttrans, tant=0;
  284.    long tst, tact;
  285.    char str[] ="xxxxx: 0000",
  286.     blk[] ="███████████";
  287.  
  288.    mouse_enable();
  289.    time(&tst);
  290.    while (!kbhit()) {
  291.       if (!sqclosed && !mouse_status) {        /* All mines discovered */
  292.      settextjustify(LEFT_TEXT, CENTER_TEXT);
  293.      setcolor(BLACK);
  294.      outtextxy(0, maxy/2-10, blk);
  295.      sprintf(str,"Mines:    0");
  296.      setcolor(LIGHTRED);
  297.      outtextxy(0, maxy/2-10, str);
  298.      settextjustify(LEFT_TEXT, CENTER_TEXT);
  299.      setcolor(BLACK);
  300.      outtextxy(0, maxy/2+10, blk);
  301.      sprintf(str," Time: %4d",ttrans);
  302.      setcolor(LIGHTGREEN);
  303.      outtextxy(0, maxy/2+10, str);
  304.      for (x=ncx-1; x>=0; x--)
  305.         for (y=ncy-1; y>=0; y--)
  306.            if (value(x,y)==MINE) {
  307.           sqmark(x,y)=1;
  308.           Set_square(x,y,1);
  309.            }
  310.      break;
  311.       }
  312.       if (cminasant != cmines) {        /* Update Mines: */
  313.      cminasant=cmines;
  314.      settextjustify(LEFT_TEXT, CENTER_TEXT);
  315.      setcolor(BLACK);
  316.      outtextxy(0, maxy/2-10, blk);
  317.      sprintf(str,"Mines: %4d",cmines);
  318.      setcolor(LIGHTRED);
  319.      outtextxy(0, maxy/2-10, str);
  320.       }
  321.       if (tant != (ttrans=(int)(time(&tact)-tst))) {    /* Update Time: */
  322.      tant=ttrans;
  323.      settextjustify(LEFT_TEXT, CENTER_TEXT);
  324.      setcolor(BLACK);
  325.      outtextxy(0, maxy/2+10, blk);
  326.      sprintf(str," Time: %4d",ttrans);
  327.      setcolor(LIGHTRED);
  328.      outtextxy(0, maxy/2+10, str);
  329.       }
  330.       mouse_read_cursor();
  331.       mouse_status&=3;
  332.       x=(mouse_x-XST)/XPX;
  333.       y=(mouse_y-YST)/YPX;
  334.       if (xant == -1) {
  335.      xant=x;
  336.      yant=y;
  337.       }
  338.       if (x!=xant || y!=yant) {                /* Position change */
  339.      if (sqpress(xant,yant) && !sqopen(xant,yant)) {
  340.         sqpress(xant,yant)=NO;
  341.         Set_square(xant,yant,1);
  342.      }
  343.      xant=x;
  344.      yant=y;
  345.       }
  346.       if (!mouse_status)
  347.      mlstant=mrstant=0;
  348.       if ((mouse_status == 2) &&
  349.        !sqopen(x,y)       &&
  350.        mlstant!=mouse_status) {    /* Right button pressed */
  351.      mlstant=mouse_status;
  352.      mouse_disable();
  353.      switch (sqmark(x,y)=(sqmark(x,y)+1) % 3) {
  354.         case 1 : cmines--; break;
  355.         case 2 : cmines++;
  356.      }
  357.      Set_square(x,y,1);
  358.      mouse_enable();
  359.       }
  360.       else if (mouse_status==1 &&    /* Left button pressed */
  361.            !sqopen(x,y)    &&
  362.            !sqpress(x,y)   &&    /* And square not pressed */
  363.            sqmark(x,y)!=1) {
  364.      sqpress(x,y)=YES;
  365.      Set_square(x,y,0);
  366.       }
  367.       else if (!mouse_status &&        /* Left button released */
  368.            !sqopen(x,y)  &&
  369.            sqpress(x,y)  &&
  370.            sqmark(x,y)!=1) {        /* Open the square */
  371.      if (value(x,y) == MINE) {
  372.         Blow_up();
  373.         break;
  374.      }
  375.      else
  376.         Open_square(x,y);
  377.       }
  378.       else if (mouse_status==3 &&
  379.            sqopen(x,y)     &&
  380.            mrstant!=mouse_status) {    /* Open near squares */
  381.      mrstant=mouse_status;
  382.      if (Open_near_squares(x,y) == YES) {
  383.         Blow_up();
  384.         break;
  385.      }
  386.       }
  387.    }
  388.    mouse_disable();
  389.    return (getch());
  390. }    /* Do_all */
  391.  
  392. /*----------------------------------------------------------------------*/
  393.  
  394. void Blow_up(void)
  395. {
  396.    int x, y, xl, yt, xr, yb;
  397.  
  398.    mouse_disable();
  399.    for (x=0; x<ncx; x++) {
  400.       for (y=0; y<ncy; y++) {
  401.      if (value(x,y) == MINE) {
  402.         settextjustify(CENTER_TEXT, CENTER_TEXT);
  403.         setcolor(LIGHTRED);
  404.         outtextxy(XST+XPX*x+XPX/2-1, YST+YPX*y+YPX/2, "█");
  405.         setcolor(BLACK);
  406.         outtextxy(XST+XPX*x+XPX/2, YST+YPX*y+YPX/2+1, "*");
  407.      }
  408.      else if (sqmark(x,y)==1) {
  409.         setcolor(YELLOW);
  410.         xl=XST+XPX*x;
  411.         xr=xl+XPX-1;
  412.         yt=YST+YPX*y;
  413.         yb=yt+YPX-1;
  414.         line(xl,yt,xr,yb);
  415.         line(xl,yb,xr,yt);
  416.      }
  417.       }
  418.    }
  419. }    /* Blow_up */
  420.  
  421. /*----------------------------------------------------------------------*/
  422.  
  423. void Open_square(int x, int y)
  424. {
  425.    char num[2]="0";
  426.    int a, b, c;
  427.  
  428.    sqopen(x,y)=YES;
  429.    if ((num[0]=value(x,y)) != 0) {
  430.       num[0]+='0';
  431.       switch(num[0]) {
  432.      case '1' : c=LIGHTBLUE; break;
  433.      case '2' : c=LIGHTGREEN; break;
  434.      case '3' : c=YELLOW; break;
  435.      case '4' : c=LIGHTRED; break;
  436.      default  : c=LIGHTMAGENTA;
  437.       }
  438.       mouse_disable();
  439.       setcolor(c);
  440.       settextjustify(CENTER_TEXT, CENTER_TEXT);
  441.       outtextxy(XST+XPX*x+XPX/2, YST+YPX*y+YPX/2+1, num);
  442.       mouse_enable();
  443.    }
  444.    else {        /* Open near squares if the current number is 0 */
  445.       a=x-1;
  446.       b=y-1;
  447.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  448.      Set_square(a,b,0);
  449.      Open_square(a,b);
  450.       }
  451.       a++;
  452.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  453.      Set_square(a,b,0);
  454.      Open_square(a,b);
  455.       }
  456.       a++;
  457.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  458.      Set_square(a,b,0);
  459.      Open_square(a,b);
  460.       }
  461.       b++;
  462.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  463.      Set_square(a,b,0);
  464.      Open_square(a,b);
  465.       }
  466.       a-=2;
  467.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  468.      Set_square(a,b,0);
  469.      Open_square(a,b);
  470.       }
  471.       b++;
  472.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  473.      Set_square(a,b,0);
  474.      Open_square(a,b);
  475.       }
  476.       a++;
  477.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  478.      Set_square(a,b,0);
  479.      Open_square(a,b);
  480.       }
  481.       a++;
  482.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  483.      Set_square(a,b,0);
  484.      Open_square(a,b);
  485.       }
  486.    }
  487. }    /* Open_square */
  488.  
  489. /*----------------------------------------------------------------------*/
  490.  
  491. /*
  492.    Open the sorrounded squares. Returns != 0 if I activated a mine
  493. */
  494. int Open_near_squares(int x, int y)
  495. {
  496.    int a, b, suma=0;
  497.  
  498.    a=x-1;
  499.    b=y-1;
  500.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  501.       suma++;
  502.    a++;
  503.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  504.       suma++;
  505.    a++;
  506.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  507.       suma++;
  508.    b++;
  509.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  510.       suma++;
  511.    a-=2;
  512.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  513.       suma++;
  514.    b++;
  515.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  516.       suma++;
  517.    a++;
  518.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  519.       suma++;
  520.    a++;
  521.    if (a>=0 && b>=0 && a<ncx && b<ncy && sqmark(a,b)==1)
  522.       suma++;
  523.    if (suma == value(x,y)) {
  524.       suma=0;
  525.       a=x-1;
  526.       b=y-1;
  527.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  528.      suma|=(value(a,b)==MINE);
  529.      Set_square(a,b,0);
  530.      Open_square(a,b);
  531.       }
  532.       a++;
  533.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  534.      suma|=(value(a,b)==MINE);
  535.      Set_square(a,b,0);
  536.      Open_square(a,b);
  537.       }
  538.       a++;
  539.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  540.      suma|=(value(a,b)==MINE);
  541.      Set_square(a,b,0);
  542.      Open_square(a,b);
  543.       }
  544.       b++;
  545.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  546.      suma|=(value(a,b)==MINE);
  547.      Set_square(a,b,0);
  548.      Open_square(a,b);
  549.       }
  550.       a-=2;
  551.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  552.      suma|=(value(a,b)==MINE);
  553.      Set_square(a,b,0);
  554.      Open_square(a,b);
  555.       }
  556.       b++;
  557.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  558.      suma|=(value(a,b)==MINE);
  559.      Set_square(a,b,0);
  560.      Open_square(a,b);
  561.       }
  562.       a++;
  563.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  564.      suma|=(value(a,b)==MINE);
  565.      Set_square(a,b,0);
  566.      Open_square(a,b);
  567.       }
  568.       a++;
  569.       if (a>=0 && b>=0 && a<ncx && b<ncy && !sqopen(a,b) && sqmark(a,b)!=1) {
  570.      suma|=(value(a,b)==MINE);
  571.      Set_square(a,b,0);
  572.      Open_square(a,b);
  573.       }
  574.       return (suma);
  575.    }
  576.    else
  577.       return 0;
  578. }    /* Open_near_squares */
  579.